package com.jh.concurrent.juc.condition;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author JH_Wong
 * @projectName newforward
 * @title ReentConditionQueue.java
 * @package com.jh.concurrent.juc.condition
 * @description 使用ReentrantLock和Condition实现阻塞队列
 * @date 2019-05-21 10:33
 */
public class ReentConditionQueue<T> {

    private List<T> queues;
    private Integer fullSize;

    private ReentrantLock lock;
    private Condition putCondition;
    private Condition takeCondition;

    public ReentConditionQueue(Integer size) {
        lock = new ReentrantLock();
        putCondition = lock.newCondition();
        takeCondition = lock.newCondition();

        fullSize = size;
        queues = new ArrayList<>(size);
    }

    public T take() {

        lock.lock();

        try {
            for (; ; ) {
                if (queues.size() == 0) {
                    System.out.println("当前线程：" + Thread.currentThread().getName() + " 当前容量：" + queues.size() + " await() 空了；");
                    takeCondition.await();
                } else {
                    break;
                }
            }

            System.out.println("当前线程：" + Thread.currentThread().getName() + " 当前容量：" + queues.size() + " 成功take；");
            return queues.remove(0);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            putCondition.signalAll();
            lock.unlock();
        }

        return null;
    }

    public void put(T tmp) {
        lock.lock();

        try {
            for (; ; ) {
                if (queues.size() == fullSize) {
                    System.out.println("当前线程：" + Thread.currentThread().getName() + " 当前容量：" + queues.size() + " await() 满了；");
                    putCondition.await();
                } else {
                    break;
                }
            }

            queues.add(tmp);
            System.out.println("当前线程：" + Thread.currentThread().getName() + " 当前容量：" + queues.size() + " 成功add；");

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            takeCondition.signalAll();
            lock.unlock();
        }
    }

}
